package cn.com.acca.ma.service.impl;

import cn.com.acca.ma.common.util.DateUtil;
import cn.com.acca.ma.common.util.PropertiesUtil;
import cn.com.acca.ma.constant.RobotName;
import cn.com.acca.ma.model.*;
import cn.com.acca.ma.pojo.MaxAndMin;
import cn.com.acca.ma.service.ModelMACDGoldCrossService;
import cn.com.acca.ma.service.ModelStockIndexMACDGoldCrossService;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.RectangleInsets;

import java.awt.*;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class ModelStockIndexMACDGoldCrossServiceImpl extends BaseServiceImpl<ModelStockIndexMACDGoldCrossServiceImpl, ModelStockIndexMACDGoldCross> implements ModelStockIndexMACDGoldCrossService {

    /*********************************************************************************************************************
     *
     * 												计算全部数据
     *
     *********************************************************************************************************************/
    /**
     * 使用日线级别MACD金叉模型算法，向表MDL_STOCK_INDEX_MACD_G_C插入数据
     */
    @Override
    public void writeModelStockIndexMACDGoldCross() {
        modelStockIndexMACDGoldCrossDao.writeModelStockIndexMACDGoldCross();
    }

    /*********************************************************************************************************************
     *
     * 												创建图表
     *
     *********************************************************************************************************************/
    /**
     * 创建MDL_STOCK_INDEX_MACD_G_C表的收益率图
     */
    @Override
    public void createModelStockIndexMACDGoldCrossProfitRatePicture(){
        String beginDate = PropertiesUtil
                .getValue(MODEL_STOCK_INDEX_PICTURE_PROPERTIES, "model.stock.index.beginDate");
        String endDate = PropertiesUtil
                .getValue(MODEL_STOCK_INDEX_PICTURE_PROPERTIES, "model.stock.index.endDate");
        List<String> stockIndexCodeList = PropertiesUtil
                .getList(MODEL_STOCK_INDEX_PICTURE_PROPERTIES, "model.stock.index");
        List<String> typeList = PropertiesUtil
                .getList(MODEL_STOCK_INDEX_PICTURE_PROPERTIES, "model.stock.index.type");

        // 验证参数
        if (null == stockIndexCodeList || null == typeList || stockIndexCodeList.size() == 0 || typeList.size() == 0){
            logger.warn("文件【" + MODEL_STOCK_INDEX_PICTURE_PROPERTIES +"】中的参数model.stock.index和" +
                    "model.stock.index.type至少有一个为空");
            return;
        }

        for (String stockIndexCode : stockIndexCodeList){
            for (String type : typeList){
                List<ModelStockIndexMACDGoldCross> modelStockIndexMACDGoldCrossList = modelStockIndexMACDGoldCrossDao.findByTypeAndIndexCodeOrderBySellDateAsc(Integer.valueOf(type), stockIndexCode);
                List<ModelStockIndexClosePriceMA5GoldCross> modelStockIndexClosePriceMA5GoldCrossList = modelStockIndexClosePriceMA5GoldCrossDao.findByTypeAndIndexCodeOrderBySellDateAsc(Integer.valueOf(type), stockIndexCode);
                List<ModelStockIndexHeiKinAshiDownUp> modelStockIndexHeiKinAshiDownUpList = modelStockIndexHeiKinAshiDownUpDao.findByTypeAndIndexCodeOrderBySellDateAsc(Integer.valueOf(type), stockIndexCode);
                List<ModelStockIndexKDGoldCross> modelStockIndexKDGoldCrossList = modelStockIndexKDGoldCrossDao.findByTypeAndIndexCodeOrderBySellDateAsc(Integer.valueOf(type), stockIndexCode);
                List<StockIndex> stockIndexList = stockIndexDao.getDataForLineChart(false, beginDate, endDate, stockIndexCode);
                List<MaxAndMin> maxAndMinList = stockIndexDao.getMaxMinClosePriceBetween(stockIndexCode, beginDate, endDate);

                double maxClose = maxAndMinList.get(0).getMax().doubleValue();
                double minClose = maxAndMinList.get(0).getMin().doubleValue();

                TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection();
                TimeSeries modelStockIndexMACDGoldCrossProfitRateTimeSeries = new TimeSeries("MACD金叉算法收益率", org.jfree.data.time.Day.class);
                TimeSeries modelStockIndexClosePriceMA5GoldCrossProfitRateTimeSeries = new TimeSeries("收盘价金叉MA5算法收益率", org.jfree.data.time.Day.class);
                TimeSeries modelStockIndexHeiKinAshiDownUpProfitRateTimeSeries = new TimeSeries("hei kin ashi上涨算法收益率", org.jfree.data.time.Day.class);
                TimeSeries modelStockIndexKDGoldCrossProfitRateTimeSeries = new TimeSeries("KD金叉算法收益率", org.jfree.data.time.Day.class);
                TimeSeries stockIndexTimeSeries = new TimeSeries("指数", org.jfree.data.time.Day.class);

                // 指数（上证指数、深证成指、中小板指数、创业板指数之一）
                for (int i = 0; i < stockIndexList.size(); i++) {
                    StockIndex stockIndex = stockIndexList.get(i);
                    int year = DateUtil.getYearFromDate(stockIndex.getDate());
                    int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                    int day = DateUtil.getDateFromDate(stockIndex.getDate());
                    Double value = Double.valueOf(stockIndex.getClosePrice().doubleValue());
                    stockIndexTimeSeries.addOrUpdate(new Day(day, month, year), this.averageCloseAfterAdjust(value, maxClose, minClose));
                }
                timeSeriesCollection.addSeries(stockIndexTimeSeries);

                // MACD金叉算法收益率
                for (int i = 0, j = 0; i < stockIndexList.size() && j < modelStockIndexMACDGoldCrossList.size(); ) {
                    Date stockIndexDate = stockIndexList.get(i).getDate();
                    Date modelStockIndexMACDGoldCrossSellDate = modelStockIndexMACDGoldCrossList.get(j).getSellDate();

                    if (stockIndexDate.equals(modelStockIndexMACDGoldCrossSellDate)) {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        double value = Double.parseDouble(modelStockIndexMACDGoldCrossList.get(j).getAccumulativeProfitLoss().toString());
                        modelStockIndexMACDGoldCrossProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), value);
                        i++;
                        j++;
                    } else if (stockIndexDate.before(modelStockIndexMACDGoldCrossSellDate)) {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        modelStockIndexMACDGoldCrossProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), null);
                        i++;
                    } else {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        modelStockIndexMACDGoldCrossProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), null);
                        j++;
                    }
                }
                timeSeriesCollection.addSeries(modelStockIndexMACDGoldCrossProfitRateTimeSeries);

                // 收盘价金叉MA5算法收益率
                for (int i = 0, j = 0; i < stockIndexList.size() && j < modelStockIndexClosePriceMA5GoldCrossList.size(); ) {
                    Date stockIndexDate = stockIndexList.get(i).getDate();
                    Date modelStockIndexClosePriceMA5GoldCrossSellDate = modelStockIndexClosePriceMA5GoldCrossList.get(j).getSellDate();

                    if (stockIndexDate.equals(modelStockIndexClosePriceMA5GoldCrossSellDate)) {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        double value = Double.parseDouble(modelStockIndexClosePriceMA5GoldCrossList.get(j).getAccumulativeProfitLoss().toString());
                        modelStockIndexClosePriceMA5GoldCrossProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), value);
                        i++;
                        j++;
                    } else if (stockIndexDate.before(modelStockIndexClosePriceMA5GoldCrossSellDate)) {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        modelStockIndexClosePriceMA5GoldCrossProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), null);
                        i++;
                    } else {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        modelStockIndexClosePriceMA5GoldCrossProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), null);
                        j++;
                    }
                }
                timeSeriesCollection.addSeries(modelStockIndexClosePriceMA5GoldCrossProfitRateTimeSeries);

                // hei kin ashi上涨算法收益率
                for (int i = 0, j = 0; i < stockIndexList.size() && j < modelStockIndexHeiKinAshiDownUpList.size(); ) {
                    Date stockIndexDate = stockIndexList.get(i).getDate();
                    Date modelStockIndexHeiKinAshiDownUpSellDate = modelStockIndexHeiKinAshiDownUpList.get(j).getSellDate();

                    if (stockIndexDate.equals(modelStockIndexHeiKinAshiDownUpSellDate)) {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        double value = Double.parseDouble(modelStockIndexHeiKinAshiDownUpList.get(j).getAccumulativeProfitLoss().toString());
                        modelStockIndexHeiKinAshiDownUpProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), value);
                        i++;
                        j++;
                    } else if (stockIndexDate.before(modelStockIndexHeiKinAshiDownUpSellDate)) {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        modelStockIndexHeiKinAshiDownUpProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), null);
                        i++;
                    } else {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        modelStockIndexHeiKinAshiDownUpProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), null);
                        j++;
                    }
                }
                timeSeriesCollection.addSeries(modelStockIndexHeiKinAshiDownUpProfitRateTimeSeries);

                // KD金叉算法收益率
                for (int i = 0, j = 0; i < stockIndexList.size() && j < modelStockIndexKDGoldCrossList.size(); ) {
                    Date stockIndexDate = stockIndexList.get(i).getDate();
                    Date modelStockIndexKDGoldCrossSellDate = modelStockIndexKDGoldCrossList.get(j).getSellDate();

                    if (stockIndexDate.equals(modelStockIndexKDGoldCrossSellDate)) {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        double value = Double.parseDouble(modelStockIndexKDGoldCrossList.get(j).getAccumulativeProfitLoss().toString());
                        modelStockIndexKDGoldCrossProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), value);
                        i++;
                        j++;
                    } else if (stockIndexDate.before(modelStockIndexKDGoldCrossSellDate)) {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        modelStockIndexKDGoldCrossProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), null);
                        i++;
                    } else {
                        StockIndex stockIndex = stockIndexList.get(i);
                        int year = DateUtil.getYearFromDate(stockIndex.getDate());
                        int month = DateUtil.getMonthFromDate(stockIndex.getDate());
                        int day = DateUtil.getDateFromDate(stockIndex.getDate());
                        modelStockIndexKDGoldCrossProfitRateTimeSeries.addOrUpdate(new Day(day, month, year), null);
                        j++;
                    }
                }
                timeSeriesCollection.addSeries(modelStockIndexKDGoldCrossProfitRateTimeSeries);

                // 配置字体
                // X轴字体
                Font xFont = new Font("宋体", Font.PLAIN, 40);
                // Y轴字体
                Font yFont = new Font("宋体", Font.PLAIN, 40);
                // 底部字体
                Font bottomFont = new Font("宋体", Font.PLAIN, 40);
                // 图片标题字体
                Font titleFont = new Font("隶书", Font.BOLD, 50);

                JFreeChart jfreechart = ChartFactory.createTimeSeriesChart("四种算法的收益率与指数",
                        "时间", "收益率", timeSeriesCollection, true, true, true);

                jfreechart.setBackgroundPaint(Color.white);
                // 图片标题
                jfreechart.setTitle(new TextTitle(jfreechart.getTitle().getText(), titleFont));
                // 底部字体
                jfreechart.getLegend().setItemFont(bottomFont);

                XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
                xyPlot.setBackgroundPaint(Color.lightGray);
                xyPlot.setDomainGridlinePaint(Color.white);
                xyPlot.setRangeGridlinePaint(Color.white);
                xyPlot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));
                xyPlot.setDomainCrosshairVisible(true);
                xyPlot.setRangeCrosshairVisible(true);
                xyPlot.getDomainAxis();

                // X轴
                ValueAxis domainAxis = xyPlot.getDomainAxis();
                // X轴标题字体
                domainAxis.setLabelFont(xFont);
                // Y轴
                ValueAxis rangeAxis = xyPlot.getRangeAxis();
                // Y轴标题字体
                rangeAxis.setLabelFont(yFont);

                org.jfree.chart.renderer.xy.XYItemRenderer xyItemRenderer = xyPlot.getRenderer();
                // 设置所有线条粗细
                xyItemRenderer.setStroke(new BasicStroke(5.0F));
                if (xyItemRenderer instanceof XYLineAndShapeRenderer) {
                    XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyItemRenderer;
                    xylineandshaperenderer.setBaseShapesVisible(true);
                    xylineandshaperenderer.setBaseShapesFilled(true);
                    xylineandshaperenderer.setSeriesPaint(2, Color.BLACK);
                }
                DateAxis dateaxis = (DateAxis) xyPlot.getDomainAxis();
                dateaxis.setDateFormatOverride(new SimpleDateFormat("yyyy-MM-dd"));

                try {
                    FileOutputStream fos = new FileOutputStream(PICTURE_PATH + "model_stock_index_profit_rate/" + type + "_" + stockIndexCode + "_" + beginDate + "-" + endDate + PICTURE_FORMAT);
                    // 将统计图标输出成JPG文件
                    ChartUtilities.writeChartAsJPEG(fos, // 输出到哪个输出流
                            1, // JPEG图片的质量，0~1之间
                            jfreechart, // 统计图标对象
                            imageWidth,// 宽
                            IMAGE_HEIGHT,// 高
                            null // ChartRenderingInfo 信息
                    );
                    fos.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public String listToString(List list) {
        return null;
    }
}
